#include "BlockLibrary.h"
#include "base.h"
#include "Types.h"
BlockLibrary::BlockLibrary(void)
{
	m_pBlockTemplates = NULL;
	m_pRegisteredBy = NULL;
	UnloadAllBlockTemplates();
}
BlockLibrary::~BlockLibrary(void)
{
}
void BlockLibrary::PreCalculateBlockTextureMappings()
{
	map<uint, BlockTemplatePtr>::iterator it = m_blockTemplates.begin();
	vector2 tiling =  vector2(16,16);
	for(; it != m_blockTemplates.end(); it++)
	{
		//Only use 16*16 Tile maps
		it->second->GetTextureIndex().PreCalculateUVs(tiling);
	}
}
void BlockLibrary::UnloadAllBlockTemplates()
{
	m_blockTemplates.clear();
	m_registeredBy.clear();
}
uint BlockLibrary::GetMaxEntryID() const
{
	map<uint, BlockTemplatePtr>::const_iterator cit = m_blockTemplates.begin();
	uint maxID = 0;
	while(cit != m_blockTemplates.end())
	{
		maxID = max(maxID, (cit++)->second->GetID());
	}
	return maxID;
}
void BlockLibrary::BuildBlockLibrary()
{
	ADelete(m_pBlockTemplates);
	ADelete(m_pRegisteredBy);
	m_nBuildLibrarySize = GetMaxEntryID() + 1;
	m_pBlockTemplates = new BlockTemplatePtr[m_nBuildLibrarySize];
	m_pRegisteredBy = new IContentLoader*[m_nBuildLibrarySize];
	memset(m_pRegisteredBy, 0, sizeof(IContentLoader*) * m_nBuildLibrarySize);

	//Add all elements to an array
	map<uint, IContentLoader*>::iterator it = m_registeredBy.begin();
	while(it != m_registeredBy.end())
	{
		uint d = it->first;
		m_pBlockTemplates[it->first] = m_blockTemplates[it->first];
		m_pRegisteredBy[it->first] = it->second;
		it++;
	}
}
int BlockLibrary::RegisterBlockTemplate(BlockTemplatePtr pBlock, IContentLoader *caller)
{
	if(caller == NULL)
		return BL_LOADER_ERROR;

	//Check for duplicate block id's
	if(m_blockTemplates.find(pBlock->GetID()) != m_blockTemplates.end())
	{
		Error(cout << "Duplicate block entry found while [" << caller->GetInstanceName() << 
			"] was trying to register block ID-" << pBlock->GetID() <<
			", Already registered by [" << m_registeredBy[pBlock->GetID()]->GetInstanceName() << "]");
		return BL_DUPLICATE_BLOCK;
	}
	
	uint id = pBlock->GetID();
	m_blockTemplates[id] = pBlock;
	m_registeredBy[id] = caller;
	CPrint(IGREEN, cout << "Block " << pBlock->GetID() << ";" << pBlock->GetInternalBlockName() <<
		" registered by [" << caller->GetInstanceName() << "]");
	return pBlock->GetID();
}
int BlockLibrary::GetFreeBlockID() const
{
	if(m_blockTemplates.empty())
		return BlockID_ReservedStart; // Return first available id;
	map<uint, BlockTemplatePtr>::const_iterator it = m_blockTemplates.begin();
	int prevId = BlockID_ReservedStart;
	int deltaId = 0;
	for(; it != m_blockTemplates.end(); it++)
	{
		deltaId = it->first - prevId;
		//Gap found between Id's
		if(deltaId > 1)
			return (prevId+1);
		prevId = it->first;
	}
	return (prevId+1); // Return last Id + 1
}
const MultiTextureIndex &BlockLibrary::GetBlockTextureInfo(uint blockID) const
{
	return m_pBlockTemplates[blockID]->GetTextureIndex();
}
uint BlockLibrary::GetBlockRenderType(uint blockID) const
{
	return m_pBlockTemplates[blockID]->GetRenderType();
}